/*
The main header file for DDMCMC algorithm.
*/
#ifndef _DDMCMC
#define _DDMCMC

#include <fstream>
#include <iostream>
#include <time.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include "ddmcmc_meanshift.h"
#include "Matrix.h"
#include "mcRaster.h"
#include "mcRasterColor.h"
#include "mcmcMap.h"
#include "mcmcSymphony.h"
#include "mcEdgeOp.h"
#include "mcRand.h"
#include "mcmcException.h"
#include "CgEdgePrcs.h"

using namespace cv;
using namespace std;

#define PIXELS_1080P 2073600
#define PIXELS_720P 921600

extern long long tTotal;
extern long long tFunction;
extern long long tStart;


class DDMCMC_Settings {
public:
	// constructor and destructor
	DDMCMC_Settings();
	~DDMCMC_Settings();

	// operator
	// DDMCMC_Settings& operator=(const DDMCMC_Settings a);

public:
	int		nHeight, nWidth;
	int		nStepFrom, nStepTo;
	double	dScale;
	bool	bSaveSeg;
	bool	bColor;
	bool	bTexture;
	bool	bSameSize;
	int		nHeightseg, nWidthseg;
	bool	bLoadData;
};

class DDMCMC {
public:
	// constructor and destructor
	DDMCMC();
	~DDMCMC();

	// main function
	bool DDMCMCSegmentation(Mat mInputimg, int stepFrom = 0, int stepTo = 10, double scale = 12.0, bool visualize = false);

public:
	// helper functions
	void generateProposal(Raster_Color<uchar> &image_color, bool visualize = 1);
	void clearWorkspace();
	void settingInitialize(int stepFrom = 0, int stepTo = 10, double scale = 12.0, bool visualize = false);
	void setImg(Mat mInputimg);
	Mat synthesize();
	//Mat boundaries();
	void RunDDMCMCSegmentation(Raster_Color<uchar> &raster, mcmcMatrix<int> imageLabel[3], int num_label[], Raster<int> &image_init, const MCMC_SegSetting& setting1, char *str_file_name = NULL);

private:
	MCMC_SegSetting setting;
	mcmcMatrix<int>		partition_maps[3];
	int num[3];
	mcmcMatrix<int>		ms_clustering;
	Raster<int>		mx_labelmap;
	MCMC_Map_2Layers *pmap;
	MCMC_Conductor	*m_pmcmc_conductor;

private:
	Mat mImg, mResult, mSynResult, mBoundaries;
	DDMCMC_MeanShiftClustering *msClustering;

public: // results
	Mat getVisualized(){ return mResult.clone(); }
	Mat getBoundaries(){ return mBoundaries.clone(); }
	Mat getSynthesized(){ return mSynResult.clone(); };
};

bool DDMCMCSegmentation(Mat img);

__forceinline void startTimer() {
	tStart = GetTickCount();
}
__forceinline void stopTimer() {
	tFunction += GetTickCount() - tStart;
}

#endif